package com.springboot.system.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.springboot.system.dao.UserDao;
import com.springboot.system.domain.auth.ClientInfo;
import com.springboot.system.domain.auth.Department;
import com.springboot.system.domain.auth.Job;
import com.springboot.system.domain.auth.LoginVO;
import com.springboot.system.domain.auth.ModifyPwdVO;
import com.springboot.system.domain.auth.Permission;
import com.springboot.system.domain.auth.Role;
import com.springboot.system.domain.auth.UserInfo;
import com.springboot.system.domain.auth.UserInfoVO;
import com.springboot.system.domain.auth.UserRole;

import com.springboot.common.algorithm.DepartmentAlgorithm;
import com.springboot.common.algorithm.PermissionAlgorithm;
import com.springboot.common.constant.DataScopeType;
import com.springboot.common.exception.SystemException;
import com.springboot.common.utils.BeanUtils;
import com.springboot.common.utils.DateUtils;
import com.springboot.common.utils.HttpUtils;
import com.springboot.common.utils.MD5Utils;
import com.springboot.common.utils.StringUtils;
import com.springboot.common.utils.UUIDUtils;
import com.springboot.core.AuthUserHolder;
import com.springboot.core.SysManager;
import com.springboot.core.TokenInfo;
import com.springboot.core.web.mvc.Page;
import com.springboot.core.web.spring.SpringMVCUtil;

/**
 * 用户业务层实现类
 * 
 * @ClassName: UserService
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author 252956
 * @date 2021年1月7日 上午9:47:58
 *
 */
@Service
public class UserService {
	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleService roleService;
	@Autowired
	private PermissionService permissionService;
	@Autowired
	private DepartmentService departmentService;
	@Autowired
	private JobService jobService;
	@Autowired
	private OnlineUserService onlineUserService;

	public TokenInfo login(LoginVO vo) {
		if (StringUtils.isBlank(vo.getUsername())) {
			throw new SystemException("用户名不能为空");
		}
		if (StringUtils.isBlank(vo.getPassword())) {
			throw new SystemException("密码不能为空");
		}
		loginProcess(vo);

		return AuthUserHolder.getTokenInfo();
	}

	private UserInfo loginProcess(LoginVO vo) {

		// 根据登陆名
		UserInfo user = userDao.selectOne(new UserInfo().setName(vo.getUsername()));
		if (user == null) {
			throw new SystemException("无效的用户名或密码");
		}
		String md5password = MD5Utils.getMD5Encoding(vo.getPassword());
		if (!user.getPassword().equals(md5password)) {
			throw new SystemException("无效的用户名或密码");
		}
		if (AuthUserHolder.user_unable.equals(user.getStatus())) {
			throw new SystemException("该账户已被禁用");
		}

		// --- 如果不允许并发登录，则将这个账号的历史登录标记为：被顶下线
		if (!SysManager.getConfig().getIsConcurrent()) {
			onlineUserService.kickoutByUId(user.getUid());
		}

		// 生成token
		String tokenValue = AuthUserHolder.generateToken();

		// 将token放到当前请求
		SpringMVCUtil.getRequest().setAttribute(SysManager.getConfig().getTokenName(), tokenValue);
		// 客户端信息
		ClientInfo clientInfo = new ClientInfo();
		clientInfo.setIp(HttpUtils.getIpAddr(SpringMVCUtil.getRequest()));
		clientInfo.setLoginTime(new Date());
		user.setClientInfo(clientInfo);

		// 将用户信息存入缓存
		AuthUserHolder.setUserInfo(user);

		return user;
	}

	public UserInfoVO info() {
		UserInfo user = AuthUserHolder.getUserInfo();
		// 获取当前用户的所属公司
		Department company = DepartmentAlgorithm.findCompany(user.getDeptId(), departmentService.selectAll());
		if (company == null) {
			throw new SystemException("未查询到当前用户的所属公司");
		}
		// 部门
		Department dept = departmentService.select(user.getDeptId());
		if (dept == null) {
			throw new SystemException("未查询到当前用户的部门");
		}
		if (user.getJobId() != null) {
			// 岗位
			Job job = jobService.select(user.getJobId());
			if (job != null) {
				user.setJobName(job.getName());
			}
		}
		// 角色
		List<Role> roleList = roleService.selectByUser(user.getUid());
		if (roleList == null || roleList.isEmpty()) {
			throw new SystemException("当前用户未分配角色");
		}
		List<Integer> roleIdList = roleList.stream().map(Role::getId).collect(Collectors.toList());
		// 角色对应的权限
		List<Permission> permissionList = permissionService
				.selectByRole(roleIdList.toArray(new Integer[roleIdList.size()]));

		if (permissionList == null || permissionList.isEmpty()) {
			throw new SystemException("当前用户未分配权限");
		}

		// 找出用户角色拥有最大的数据权限
		Integer datascopeType = roleList.stream().min((e1, e2) -> e1.getData_scope().compareTo(e1.getData_scope()))
				.get().getData_scope();
		user.setDeptName(dept.getName());
		user.setCompanyId(company.getId());
		user.setCompanyName(company.getName());
		user.setRoleList(roleList);
		user.setRoleNameList(roleList.stream().map(Role::getName).collect(Collectors.toList()));
		user.setPermissionCodeList(permissionList.stream().filter(e -> !e.isMenu()).map(Permission::getPermissionFlag)
				.collect(Collectors.toList()));
		user.setMenuList(permissionList.stream().filter(e -> e.isMenu()).collect(Collectors.toList()));
		user.setDatascopeType(datascopeType);
		user.setDatascopeList(getDataScopeList(user));
		AuthUserHolder.setUserInfo(user);

		UserInfoVO userInfoVO = new UserInfoVO();
		BeanUtils.copyProperties(user, userInfoVO);
		userInfoVO.setRoleNameList(user.getRoleNameList());
		userInfoVO.setPermissionCodeList(user.getPermissionCodeList());
		userInfoVO.setMenuList(PermissionAlgorithm.buildMenu(PermissionAlgorithm.tree(user.getMenuList())));
		userInfoVO.setPassword("");

		return userInfoVO;
	}

	/***
	 * 获取角色对应的数据权限
	 *
	 * @param @param  roles
	 * @param @return 设定文件
	 * @return List<Integer> 返回类型
	 *
	 */
	private List<Integer> getDataScopeList(UserInfo user) {
		List<Integer> dataScopeList = new ArrayList<Integer>();
		List<Department> allDeptList = departmentService.selectAll();
		for (Role role : user.getRoleList()) {
			// 1全部数据权限
			if (DataScopeType.all.equals(role.getData_scope())) {
				for (Department dept : allDeptList) {
					dataScopeList.add(dept.getId());
				}
				// 2用户自定义数据权限
			} else if (DataScopeType.customize.equals(role.getData_scope())) {
				dataScopeList.addAll(roleService.selectDataScope(role.getId()));
				// 3本部门及以下数据权限
			} else if (DataScopeType.deptAndBelow.equals(role.getData_scope())) {
				List<Department> findSelfAndAllChild = DepartmentAlgorithm.findSelfAndAllChild(user.getDeptId(),
						allDeptList);
				for (Department dept : findSelfAndAllChild) {
					dataScopeList.add(dept.getId());
				}
				// 4本部门数据权限
			} else if (DataScopeType.dept.equals(role.getData_scope())) {
				dataScopeList.add(user.getDeptId());
			}
		}
		if (dataScopeList.isEmpty()) {
			// 5仅本人数据权限
			return null;
		}
		// 去重复
		Set<Integer> ownedSet = new HashSet<Integer>();
		for (Integer id : dataScopeList) {
			ownedSet.add(id);
		}
		dataScopeList = new ArrayList<Integer>(ownedSet);

		return dataScopeList;
	}

	public void modifyPwd(ModifyPwdVO vo) {

		if (vo == null || StringUtils.isBlank(vo.getOldPassword()) || StringUtils.isBlank(vo.getNewPassword())
				|| StringUtils.isBlank(vo.getConfirmNewPassword())) {
			throw new SystemException("必填项不能为空");
		}
		if (!vo.getNewPassword().equals(vo.getConfirmNewPassword())) {
			throw new SystemException("两次输入密码必须相同");
		}
		UserInfo user = AuthUserHolder.getUserInfo();

		if (!user.getPassword().equals(MD5Utils.getMD5Encoding(vo.getOldPassword()))) {
			throw new SystemException("原密码错误");
		}

		UserInfo userInfo = userDao.select(user.getUid());
		if (userInfo == null) {
			throw new SystemException("用户不存在");
		}
		userInfo.setPassword(MD5Utils.getMD5Encoding(vo.getNewPassword()));
		userDao.update(userInfo);
		// 更新内存中的密码
		AuthUserHolder.setUserInfo(userInfo);

	}

	public Page<UserInfo> page(UserInfoVO vo) {
		Page<UserInfo> page = userDao.selectPage(vo);
		if (page.getRows() != null && !page.getRows().isEmpty()) {
			for (UserInfo userInfo : page.getRows()) {
				List<Role> roleList = roleService.selectByUser(userInfo.getUid());
				userInfo.setRoleList(roleList);
			}
		}
		return page;
	}

	@Transactional(value = "baseTransactionManager")
	public boolean add(UserInfoVO vo) throws SystemException {

		if (StringUtils.isBlank(vo.getVserName())) {
			throw new SystemException("真实姓名不能为空");
		}
		if (StringUtils.isBlank(vo.getName())) {
			throw new SystemException("登陆名不能为空");
		}
		if (StringUtils.isBlank(vo.getPassword())) {
			throw new SystemException("登陆密码不能为空");
		}
		if (vo.getDeptId() == null) {
			throw new SystemException("请选择部门");
		}
		UserInfo existUser = userDao.selectOne(new UserInfo().setName(vo.getName()));
		if (existUser != null) {
			throw new SystemException("账号已存在");
		}

		UserInfo user = new UserInfo();
		BeanUtils.copyObject(user, vo);
		user.setCreateTime(DateUtils.getDateTime());
		user.setCreator(AuthUserHolder.getUserInfo().getVserName());
		String password = MD5Utils.getMD5Encoding(user.getPassword());
		user.setPassword(password);
		user.setUid(UUIDUtils.generateUUID());
		// 保存用户信息
		int result = userDao.insert(user);
		if (result < 0) {
			throw new SystemException("保存失败");
		}

		if (vo.getRoleIdList() != null && vo.getRoleIdList().length > 0) {
			List<UserRole> urList = new ArrayList<UserRole>();
			UserRole ur;
			for (Integer roleId : vo.getRoleIdList()) {
				ur = new UserRole();
				ur.setUserId(user.getUid());
				ur.setRoleId(roleId);
				urList.add(ur);
			}
			// 保存用户分配的角色
			userDao.batchInsert(urList);
		}
		return true;
	}

	public boolean update(UserInfoVO vo) throws SystemException {

		if (vo.getUid() == null) {
			throw new SystemException("用户不存在");
		}
		if (vo.getDeptId() == null) {
			throw new SystemException("请选择部门");
		}
		UserInfo user = userDao.select(vo.getUid());
		if (user == null) {
			throw new SystemException("用户不存在");
		}
		String password = "";
		if (!user.getPassword().equals(vo.getPassword())) {
			password = MD5Utils.getMD5Encoding(vo.getPassword());
		}
		BeanUtils.copyObject(user, vo);
		if (StringUtils.isNotBlank(password)) {
			user.setPassword(password);
		}
		int result = userDao.update(user);
		if (result < 0) {
			throw new SystemException("修改失败");
		}

		// 删除用户角色
		userDao.delete(new UserRole().setUserId(user.getUid()));

		if (vo.getRoleIdList() != null && vo.getRoleIdList().length > 0) {
			List<UserRole> urList = new ArrayList<UserRole>();
			UserRole ur;
			for (Integer roleId : vo.getRoleIdList()) {
				ur = new UserRole();
				ur.setUserId(user.getUid());
				ur.setRoleId(roleId);
				urList.add(ur);
			}
			// 保存用户分配的角色
			userDao.batchInsert(urList);
		}
		return true;

	}

	public boolean delete(String uid) throws SystemException {
		if (StringUtils.isBlank(uid)) {
			throw new SystemException("uid不能为空");
		}
		int result = userDao.delete(new UserInfo().setUid(uid));
		if (result < 0) {
			throw new SystemException("删除失败");
		}
		return true;
	}

	/**
	 * 更新用户状态
	 */

	public boolean updateStatus(UserInfoVO vo) {
		if (StringUtils.isBlank(vo.getUid())) {
			throw new SystemException("uid不能为空");
		}
		int result = userDao.updateStatus(vo.getUid(), vo.getStatus());
		if (result < 0) {
			throw new SystemException("更新失败");
		}
		return true;
	}
}
